import { Injectable, Inject } from '@nestjs/common';
import { v4 as uuid } from 'uuid';
import { IToken } from '../interfaces/token.interface';
import { JwtPayload } from '../interfaces/jwt-payload.interface';
import { RedisLantService } from '../../common/services/redis-lant.service';
import { ConfigService } from '../../../modules/config/services/config.service';
import { ConfigProvider } from '../../config/constants/config.constant';
import { Guard } from '../../guard/constants/guard.constant';
import { Redis } from '../../common/constants/redis.constant';
import { Role } from '../../role/constants/role.constant';

@Injectable()
export class AuthService {
  constructor(
    @Inject(ConfigProvider)
    private readonly configService: ConfigService,
    private readonly redisLantService: RedisLantService
  ) {}

  /**
   * 创建Token
   * @param userUuid 用户Uuid
   * @param jobId 用户当前岗位/组织id列表
   * @param guardList 用户权限列表
   * @param roleList 用户角色列表
   */
  async createToken(userUuid: string, jobId: number, guardList: Guard[], roleList: Role[]): Promise<IToken> {
    //TODO:下面的判断逻辑需要重新梳理
    // const accessToken: string = await this.redisLantService.get(Redis.token, 'User_' + userUuid);
    // if (accessToken) {
    //   return {
    //     expiresIn: this.configService.common.jwtExpiresIn,
    //     accessToken: accessToken.replace('_', ' ')
    //   };
    // }

    const token = uuid();
    const newAccessToken = 'Bearer_' + token;
    const payload: JwtPayload = {
      uuid: userUuid,
      jobId: jobId,
      guardList: guardList,
      roleList: roleList
    };

    const client = this.redisLantService.getTokenClient();
    await client.psetex('User_' + userUuid, this.configService.common.jwtExpiresIn, newAccessToken);
    await client.psetex(newAccessToken, this.configService.common.jwtExpiresIn, JSON.stringify(payload));

    return {
      expiresIn: this.configService.common.jwtExpiresIn,
      accessToken: 'Bearer ' + token
    };
  }

  /**
   * 更新Token
   * @param userUuid 用户Uuid
   * @param jobId 用户当前岗位/组织id列表
   * @param guardList 用户权限列表
   * @param roleList 用户角色列表
   */
  async updateToken(userUuid: string, jobId: number, guardList?: Guard[], roleList?: Role[]): Promise<IToken> {
    const accessToken: string = await this.redisLantService.get(Redis.token, 'User_' + userUuid);
    if (!accessToken) return null;

    const payload = await this.redisLantService.get<JwtPayload>(Redis.token, accessToken);
    if (!payload) return null;

    payload.jobId = jobId;
    if (guardList) payload.guardList = guardList;
    if (roleList) payload.roleList = roleList;

    const client = this.redisLantService.getTokenClient();
    await client.psetex('User_' + userUuid, this.configService.common.jwtExpiresIn, accessToken);
    await client.psetex(accessToken, this.configService.common.jwtExpiresIn, JSON.stringify(payload));

    return {
      expiresIn: this.configService.common.jwtExpiresIn,
      accessToken: accessToken
    };
  }

  async decodeToken(token: string): Promise<JwtPayload> {
    const payload: JwtPayload = await this.redisLantService.get(Redis.token, 'Bearer_' + token);
    if (payload) {
      const client = this.redisLantService.getTokenClient();
      await client.pexpire('User_' + payload.uuid, this.configService.common.jwtExpiresIn);
      await client.pexpire('Bearer_' + token, this.configService.common.jwtExpiresIn);
    }

    return payload;
  }
}
